package com.atguigu.gmall.product.biz.impl;

import com.atguigu.gmall.common.util.Jsons;
import com.atguigu.gmall.product.biz.CategoryBizService;
import com.atguigu.gmall.product.entity.CategoryViewEntity;
import com.atguigu.gmall.product.mapper.BaseCategory1Mapper;
import com.atguigu.gmall.web.CategoryVo;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Service
public class CategoryBizServiceImpl implements CategoryBizService {

    @Autowired
    BaseCategory1Mapper category1Mapper;

    //缓存；任意一个容器类
    //本地缓存
    private Map<String, Object> cache = new ConcurrentHashMap<>();

    @Autowired
    StringRedisTemplate redisTemplate;

//    @Override //本地缓存
//    public List<CategoryVo> getCategorysTree() {
//        //1、先看缓存
//        Object categorys = cache.get("categorys");
//        if (categorys == null) {
//            //2、缓存中没有
//            //3、查询数据库
//            List<CategoryVo> vos = category1Mapper.getCategorysTree();
//            //4、放回缓存
//            cache.put("categorys", vos);
//            return vos;
//        }
//
//        //5、缓存中有直接返回
//        return (List<CategoryVo>) categorys;
//    }

    //分布式缓存
    @Override
    public List<CategoryVo> getCategorysTree() {
        //1、先查缓存
        String categorys = redisTemplate.opsForValue().get("categorys");
        //这里就可能拿到的是x
//        if ("x".equals(categorys)) {
//            //以前有人查过但是数据库无此记录
//            return null;
//        }
        if (StringUtils.isEmpty(categorys)) {
            //2、缓存中没有
            //3、回源：缓存中没有，需要回到数据的源头进行查询。
            List<CategoryVo> vos = category1Mapper.getCategorysTree();
            //4、放入缓存
            if (vos == null) {
                //5、 防止缓存穿透。即使数据库没有此数据，缓存一个x，给个短一点的过期时间
                redisTemplate.opsForValue().set("categorys", "x", 30, TimeUnit.MINUTES);
            }else {
                //6、有数据存真实数据
                redisTemplate.opsForValue().set("categorys", Jsons.toStr(vos));
            }
            return vos;
        }

        //5、缓存中有
        List<CategoryVo> categoryVos = Jsons.toObj(categorys, new TypeReference<List<CategoryVo>>() {
        });

        return categoryVos;
    }

    @Override
    public CategoryViewEntity getCategoryView(Long c3Id) {

        return category1Mapper.getCategoryView(c3Id);
    }
}
